home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / MIXTREE.PAK / MIXLINE.C < prev    next >
C/C++ Source or Header  |  1997-05-06  |  16KB  |  560 lines

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright (C) 1993 - 1995  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  MODULE:   mixline.c
  9. //
  10. //  PURPOSE:  Enumerate mixer lines and controls and add them to the 
  11. //            TreeView control.  Modify the state of the TreeView control.
  12. //
  13. //  FUNCTIONS:
  14. //    BuildMixerTree   - Gets all mixer lines and adds them to the TreeView
  15. //                       control.
  16. //    GetMixerControls - Gets all controls for a mixer line and adds them to
  17. //                       the TreeView control.
  18. //    ExpandTreeView   - Cause all the nodes and leaves of the TreeView to
  19. //                       be displayed.
  20. //    ExpandBranch     - Expand a single branch of a parent item which has
  21. //                       no parent of its own.
  22. //    ExpandChildren   - Expand all the children of a parent item.
  23. //    ItemHasChild     - Determine if an item has one or more children.
  24. //
  25. //  COMMENTS:
  26. //
  27.  
  28. #include <windows.h>                // required for all Windows applications.
  29. #include <windowsx.h>
  30. #include <memory.h>
  31.  
  32. #include "globals.h"                // prototypes specific to this application.
  33. #include "resource.h"
  34. #include "mixline.h"
  35.  
  36.  
  37. //
  38. //  FUNCTION: BuildMixerTree(HWND)
  39. //
  40. //  PURPOSE: Gets all mixer lines and adds them to the TreeView control.
  41. //                       
  42. //
  43. //  PARAMETERS:
  44. //    hwnd     - application window handle
  45. //
  46. //  RETURN VALUE:
  47. //    TRUE     - Success.
  48. //    FALSE    - Failure.
  49. //
  50. //  COMMENTS:
  51. //    
  52. //
  53.  
  54. BOOL BuildMixerTree(HWND hwnd)
  55. {    
  56.     MMRESULT result;
  57.     MIXERLINE mlDest, mlSrc;   
  58.     HTREEITEM htiDest = 0, htiSrc = 0;
  59.     DWORD dwDestination, dwSource;   
  60.     
  61.     SetCapture(GetParent(hwndTreeView));
  62.     SetCursor(LoadCursor(NULL, IDC_WAIT));
  63.  
  64.     // reset global variables for currently selected item and number of items
  65.     lCurrentItem = MIXITEM_NOSELECTION;
  66.     uMixItems = 0;
  67.  
  68.     // Clear TreeView Control
  69.     TreeView_DeleteAllItems(hwndTreeView);
  70.  
  71.     // process each destination
  72.     for (dwDestination = 0; dwDestination < MixerCaps.cDestinations; 
  73.         dwDestination++)
  74.     {       
  75.         // don't write past the end of amixii[]  
  76.         if (uMixItems > MAXMIXITEMS)
  77.         {                          
  78.             ReleaseCapture();
  79.             SetCursor(LoadCursor(NULL, IDC_ARROW));           
  80.             MessageBox(hwnd, "TreeView incomplete; MAXMIXITEMS reached", 
  81.                 "MixTree Error", MB_ICONHAND);
  82.             return (FALSE);
  83.         }      
  84.     
  85.     // initialize MIXERLINE structure
  86.     _fmemset((LPBYTE)&mlDest, 0, sizeof(MIXERLINE));               
  87.         mlDest.cbStruct = sizeof(MIXERLINE);
  88.         mlDest.dwDestination = dwDestination;   
  89.                    
  90.         // get the destination's line information                   
  91.         result = GetLineInfo(hwnd, &mlDest, MIXER_GETLINEINFOF_DESTINATION);  
  92.         if (result)
  93.         {                          
  94.             ReleaseCapture();
  95.             SetCursor(LoadCursor(NULL, IDC_ARROW));
  96.             return (FALSE);
  97.         }      
  98.         
  99.         // store this item's information  
  100.         amixii[uMixItems].dwItemType      = MIXITEM_MIXERLINE;
  101.         amixii[uMixItems].dwLineID        = mlDest.dwLineID;
  102.    
  103.         // Set up the structure for a text label, and use
  104.         // the ImageList ID iINIFileImage.
  105.         _fmemset((LPBYTE)&tvi, 0, sizeof(TV_ITEM));
  106.         tvi.mask            = TVIF_TEXT | TVIF_IMAGE | TVIF_PARAM;
  107.         tvi.iImage          =
  108.         tvi.iSelectedImage  = aImageInfo[IL_DESTLINE].uImageIndex;
  109.         tvi.pszText         = mlDest.szName;  
  110.         tvi.cchTextMax      = MIXER_LONG_NAME_CHARS;      
  111.         tvi.lParam          = uMixItems;     
  112.  
  113.         // Populate the TreeView Insert Struct
  114.         // The item is the one filled above.
  115.         // Insert it after the last item inserted at this level.
  116.         // And indicate this is a root entry.
  117.  
  118.         tvins.item         = tvi;
  119.         tvins.hParent      = TVI_ROOT;  
  120.         
  121.         // insert after previous destination if there was one    
  122.         tvins.hInsertAfter = mlDest.dwDestination ? htiDest : TVI_ROOT;       
  123.     
  124.         // Add the item to the tree
  125.         htiDest = TreeView_InsertItem(hwndTreeView, &tvins);
  126.         if (!htiDest)
  127.         {                         
  128.             ReleaseCapture();
  129.             SetCursor(LoadCursor(NULL, IDC_ARROW));           
  130.             MessageBox(hwnd, "TreeView incomplete; unable to insert item", 
  131.                 "MixTree Error", MB_ICONHAND);
  132.             return (FALSE);
  133.         }      
  134.  
  135.         // increment the count
  136.         uMixItems++;
  137.                 
  138.         // get all of the destination's controls
  139.         if (!GetMixerControls(hwnd, &mlDest, htiDest))
  140.         {
  141.             // GetMixerControls has already displayed the error message
  142.             ReleaseCapture();
  143.             SetCursor(LoadCursor(NULL, IDC_ARROW));                        
  144.             return (FALSE);
  145.         }
  146.                                
  147.         if (htiControl)
  148.             // cause source lines to be children of the last control
  149.             htiDest = htiControl;      
  150.  
  151.         // process each of the destination line's sources                                                     
  152.         for (dwSource = 0; dwSource < mlDest.cConnections; dwSource++)
  153.         {   
  154.             // don't write past the end of amixii[]                                        
  155.             if (uMixItems > MAXMIXITEMS)
  156.             {                          
  157.                 ReleaseCapture();
  158.                 SetCursor(LoadCursor(NULL, IDC_ARROW));           
  159.                 MessageBox(hwnd, "TreeView incomplete; MAXMIXITEMS reached", 
  160.                     "MixTree Error", MB_ICONHAND);
  161.                 return (FALSE);
  162.             }      
  163.  
  164.         // initialize the MIXERLINE structure
  165.         _fmemset((LPBYTE)&mlSrc, 0, sizeof(MIXERLINE));               
  166.         mlSrc.cbStruct = sizeof(MIXERLINE);
  167.         mlSrc.dwSource = dwSource;
  168.         mlSrc.dwDestination = dwDestination;
  169.  
  170.             // get the source's line information
  171.             result = GetLineInfo(hwnd, &mlSrc, MIXER_GETLINEINFOF_SOURCE);  
  172.             if (result)
  173.             {                              
  174.                 ReleaseCapture();
  175.                 SetCursor(LoadCursor(NULL, IDC_ARROW));
  176.                 return (FALSE);
  177.             }  
  178.             
  179.             // store this item's information and increment the count
  180.             amixii[uMixItems].dwItemType      = MIXITEM_MIXERLINE;
  181.             amixii[uMixItems].dwLineID        = mlSrc.dwLineID;
  182.        
  183.             // Set up the structure for a text label, and use
  184.             // the ImageList ID iINIFileImage.
  185.             tvi.mask            = TVIF_TEXT | TVIF_IMAGE | 
  186.                                   TVIF_SELECTEDIMAGE | TVIF_PARAM;
  187.             tvi.iImage          =
  188.             tvi.iSelectedImage  = aImageInfo[IL_SRCLINE].uImageIndex;
  189.             tvi.pszText         = mlSrc.szName;  
  190.             tvi.cchTextMax      = MIXER_LONG_NAME_CHARS;      
  191.             tvi.lParam          = uMixItems;     
  192.  
  193.             // Populate the TreeView Insert Struct
  194.             // The item is the one filled above.
  195.             // Insert it after the last item inserted at this level.
  196.             // And indicate this is a root entry.
  197.  
  198.             tvins.item         = tvi;
  199.             tvins.hParent      = htiDest;
  200.             tvins.hInsertAfter = mlSrc.dwSource ? htiSrc : htiDest;         
  201.                                 
  202.             // Add the item to the tree
  203.             htiSrc = TreeView_InsertItem(hwndTreeView, &tvins);
  204.             if (!htiSrc)
  205.             {                          
  206.                 ReleaseCapture();
  207.                 SetCursor(LoadCursor(NULL, IDC_ARROW));           
  208.                 MessageBox(hwnd, "TreeView incomplete; unable to insert item", 
  209.                     "MixTree Error", MB_ICONHAND);
  210.                 return (FALSE);
  211.             }              
  212.     
  213.             uMixItems++;                  
  214.             
  215.             // get all of the source's controls
  216.             if (!GetMixerControls(hwnd, &mlSrc, htiSrc))
  217.             {
  218.                 // GetMixerControls() has already displayed the error message
  219.                 ReleaseCapture();
  220.                 SetCursor(LoadCursor(NULL, IDC_ARROW));                           
  221.                 return (FALSE);
  222.             }
  223.         }
  224.     }
  225.  
  226.     // initialize TreeView display
  227.  
  228.     // get handle to root of first branch (which is the root of
  229.     // the entire TreeView control) and remember it
  230.     htiCurrentRoot = TreeView_GetRoot(hwndTreeView);
  231.  
  232.     if (fDisplayAll)
  233.         // display all destination lines expanded
  234.         ExpandTreeView();
  235.     else
  236.         // display first destination line expanded
  237.         ExpandBranch(htiCurrentRoot);
  238.        
  239.     ReleaseCapture();
  240.     SetCursor(LoadCursor(NULL, IDC_ARROW));
  241.     return (TRUE);
  242. }
  243.  
  244.  
  245. //
  246. //  FUNCTION: GetMixerControls(HWND, LPMIXERLINE, HTREEITEM)
  247. //
  248. //  PURPOSE: Obtains all the controls of a mixer line and inserts items
  249. //           for them into the TreeView control
  250. //
  251. //  PARAMETERS:
  252. //    hwnd        - application window handle.
  253. //    lpMixerLine - pointer to a MIXERLINE structure.
  254. //    htiLine     - handle to the TreeView item for the mixer line.
  255. //
  256. //  RETURN VALUE:
  257. //    TRUE     - Success.
  258. //    FALSE    - Failure.
  259. //
  260. //  COMMENTS:
  261. //    
  262. //
  263.  
  264. BOOL GetMixerControls(
  265.     HWND hwnd,
  266.     LPMIXERLINE lpMixerLine,
  267.     HTREEITEM htiLine)
  268. {    
  269.     MMRESULT result;
  270.     MIXERLINECONTROLS mlcs; 
  271.     HGLOBAL hMem;
  272.     LPSTR lpMem;   
  273.     UINT i;
  274.     int iImage;   
  275.                   
  276.     if (!lpMixerLine->cControls)
  277.         // nothing to do
  278.         return (TRUE);
  279.  
  280.     // initialize global variable for last control tree item
  281.     // GetMixerLines() uses this to insert source lines into the TreeView
  282.     // control after the destination line's controls.
  283.     htiControl = NULL;
  284.  
  285.     // initialize the MIXERLINECONTROLS structure                       
  286.     _fmemset((LPBYTE)&mlcs, 0, sizeof(MIXERLINECONTROLS));
  287.     mlcs.cbStruct = sizeof(MIXERLINECONTROLS);
  288.     mlcs.dwLineID = lpMixerLine->dwLineID;
  289.  
  290.     // MIXERLINECONTROLS uses anonymous unions, which are not supported in
  291.     // C.  The code below is conditionalized to show you how the usage
  292.     // differs between C and C++.
  293.     #if defined (__cplusplus)
  294.     mlcs.dwControlType = 0;
  295.     #else
  296.     mlcs.u.dwControlType = 0;
  297.     #endif
  298.  
  299.     mlcs.cControls = lpMixerLine->cControls;
  300.     mlcs.cbmxctrl = sizeof(MIXERCONTROL);
  301.     
  302.     hMem = GlobalAlloc(GHND, lpMixerLine->cControls * sizeof(MIXERCONTROL));
  303.     if (!hMem)    
  304.     {        
  305.         MessageBox(hwnd, "Insufficient Memory", "MixTree Error", MB_ICONHAND);
  306.         return (FALSE);
  307.     }
  308.     
  309.     lpMem = GlobalLock(hMem);
  310.     if (!lpMem)
  311.     {      
  312.         MessageBox(hwnd, "Memory Error", "MixTree Error", MB_ICONHAND);
  313.         GlobalFree(hMem);
  314.         return (FALSE);
  315.     }    
  316.     
  317.     mlcs.pamxctrl = (LPMIXERCONTROL)lpMem;    
  318.       
  319.     result = GetLineControls(hwnd, &mlcs, MIXER_GETLINECONTROLSF_ALL); 
  320.     if (result)
  321.     {               
  322.         GlobalUnlock(hMem);
  323.         GlobalFree(hMem);
  324.         return (FALSE);
  325.     }
  326.           
  327.     // process each control
  328.     for (i = 0; i < lpMixerLine->cControls; i++)
  329.     { 
  330.         // don't write past the end of amixii[]  
  331.         if (uMixItems > MAXMIXITEMS)
  332.         {                                              
  333.             MessageBox(hwnd, "TreeView incomplete; MAXMIXITEMS reached", 
  334.                 "MixTree Error", MB_ICONHAND);
  335.             GlobalUnlock(hMem);
  336.             GlobalFree(hMem);
  337.             return (FALSE);
  338.         }      
  339.  
  340.         // store this item's information and increment the count  
  341.         amixii[uMixItems].dwItemType    = MIXITEM_MIXERCONTROL;
  342.         amixii[uMixItems].dwControlID   = (mlcs.pamxctrl + i)->dwControlID;
  343.       
  344.         // Set up the structure for a text label, and use
  345.         // the ImageList ID iINIFileImage.
  346.         tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
  347.  
  348.         // select an image according to the class of the control
  349.         switch ((mlcs.pamxctrl + i)->dwControlType)
  350.         {
  351.             case MIXERCONTROL_CONTROLTYPE_CUSTOM:
  352.                 iImage = IL_CUSTOM;
  353.                 break;
  354.  
  355.             case MIXERCONTROL_CONTROLTYPE_SIGNEDMETER:
  356.             case MIXERCONTROL_CONTROLTYPE_PEAKMETER:
  357.             case MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER:
  358.                 iImage = IL_METER;
  359.                 break;
  360.  
  361.             case MIXERCONTROL_CONTROLTYPE_BOOLEAN:
  362.             case MIXERCONTROL_CONTROLTYPE_ONOFF:
  363.             case MIXERCONTROL_CONTROLTYPE_MUTE:
  364.             case MIXERCONTROL_CONTROLTYPE_MONO:
  365.             case MIXERCONTROL_CONTROLTYPE_LOUDNESS:
  366.             case MIXERCONTROL_CONTROLTYPE_STEREOENH:
  367.                 iImage = IL_SWITCH;
  368.                 break;
  369.  
  370.             case MIXERCONTROL_CONTROLTYPE_SIGNED:
  371.             case MIXERCONTROL_CONTROLTYPE_UNSIGNED:
  372.                 iImage = IL_NUMBER;
  373.                 break;
  374.  
  375.             case MIXERCONTROL_CONTROLTYPE_SLIDER:
  376.             case MIXERCONTROL_CONTROLTYPE_PAN:
  377.             case MIXERCONTROL_CONTROLTYPE_QSOUNDPAN:
  378.                 iImage = IL_SLIDER;
  379.                 break;
  380.  
  381.             case MIXERCONTROL_CONTROLTYPE_FADER:
  382.             case MIXERCONTROL_CONTROLTYPE_VOLUME:
  383.             case MIXERCONTROL_CONTROLTYPE_BASS:
  384.             case MIXERCONTROL_CONTROLTYPE_TREBLE:
  385.             case MIXERCONTROL_CONTROLTYPE_EQUALIZER:
  386.                 iImage = IL_FADER;
  387.                 break;
  388.  
  389.             case MIXERCONTROL_CONTROLTYPE_MICROTIME:
  390.             case MIXERCONTROL_CONTROLTYPE_MILLITIME:
  391.                 iImage = IL_TIME;
  392.                 break;
  393.  
  394.             case MIXERCONTROL_CONTROLTYPE_SINGLESELECT:
  395.             case MIXERCONTROL_CONTROLTYPE_MUX:
  396.             case MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT:
  397.             case MIXERCONTROL_CONTROLTYPE_MIXER:
  398.                 iImage = IL_LIST;
  399.                 break;
  400.  
  401.             default:
  402.                 // this shouldn't be reached, but just in case...
  403.                 iImage = IL_CUSTOM;
  404.                 break;
  405.         }
  406.  
  407.         tvi.iImage          = 
  408.         tvi.iSelectedImage  = aImageInfo[iImage].uImageIndex;                                
  409.         tvi.pszText         = (mlcs.pamxctrl + i)->szName;  
  410.         tvi.cchTextMax      = MIXER_LONG_NAME_CHARS;      
  411.         tvi.lParam          = uMixItems;     
  412.  
  413.         // Populate the TreeView Insert Struct
  414.         // The item is the one filled above.
  415.         // Insert it after the last item inserted at this level.
  416.         // And indicate this is a root entry.
  417.  
  418.         tvins.item         = tvi;
  419.         tvins.hParent      = htiLine;
  420.         
  421.         // insert after mixer line item if this is first control
  422.         tvins.hInsertAfter = i ? htiControl : htiLine;     
  423.     
  424.         // Add the item to the tree
  425.         htiControl = TreeView_InsertItem(hwndTreeView, &tvins);
  426.         if (!htiControl)
  427.         {               
  428.             MessageBox(hwnd, "TreeView incomplete; unable to insert item", 
  429.                 "MixTree Error", MB_ICONHAND);
  430.             GlobalUnlock(hMem);
  431.             GlobalFree(hMem);
  432.             return (FALSE);
  433.         }      
  434.     
  435.         uMixItems++;   
  436.     }
  437.                            
  438.     GlobalUnlock(hMem);
  439.     GlobalFree(hMem); 
  440.     return (TRUE);
  441. }
  442.  
  443. //
  444. //  FUNCTION: ExpandTreeView()
  445. //
  446. //  PURPOSE: Expand all of TreeView control's items.
  447. //
  448. //  PARAMETERS:
  449. //    none.
  450. //
  451. //  RETURN VALUE:
  452. //    nothing.
  453. //
  454. //  COMMENTS:
  455. //    
  456. //
  457.  
  458. #pragma warn -pia
  459. void ExpandTreeView()
  460. {
  461.     HTREEITEM htiNext = TreeView_GetRoot(hwndTreeView);
  462.  
  463.     fExpandEnabled = TRUE;
  464.  
  465.     if (ItemHasChild(htiNext))
  466.         ExpandChildren(htiNext);
  467.  
  468.     while (htiNext = TreeView_GetNextSibling(hwndTreeView, htiNext))
  469.         if (ItemHasChild(htiNext))
  470.             ExpandChildren(htiNext);
  471.  
  472.     fExpandEnabled = FALSE;
  473. }
  474. #pragma warn .pia
  475.  
  476. //
  477. //  FUNCTION: ExpandBranch(HTREEITEM)
  478. //
  479. //  PURPOSE: Expand a single branch of a TreeView control.
  480. //
  481. //  PARAMETERS:
  482. //    htiParent - handle to parent item.
  483. //
  484. //  RETURN VALUE:
  485. //    nothing.
  486. //
  487. //  COMMENTS:
  488. //    
  489. //
  490.  
  491. void ExpandBranch(HTREEITEM htiParent)
  492. {  
  493.     fExpandEnabled = TRUE;
  494.    
  495.     if (ItemHasChild(htiParent))
  496.         ExpandChildren(htiParent); 
  497.  
  498.     fExpandEnabled = FALSE; 
  499. }
  500.  
  501.  
  502. //
  503. //  FUNCTION: ExpandChildren(HTREEITEM)
  504. //
  505. //  PURPOSE: Expand all of a parent TreeView item's children.
  506. //
  507. //  PARAMETERS:
  508. //    htiParent - handle to parent item.
  509. //
  510. //  RETURN VALUE:
  511. //    nothing.
  512. //
  513. //  COMMENTS:
  514. //    
  515. //
  516.  
  517. #pragma warn -pia
  518. void ExpandChildren(HTREEITEM htiParent)
  519. {
  520.     HTREEITEM htiChild;
  521.  
  522.     TreeView_Expand(hwndTreeView, htiParent, TVE_EXPAND);
  523.  
  524.     htiChild = TreeView_GetChild(hwndTreeView, htiParent);
  525.     if (ItemHasChild(htiChild))
  526.         ExpandChildren(htiChild);
  527.  
  528.     while (htiChild = TreeView_GetNextSibling(hwndTreeView, htiChild))
  529.         if (ItemHasChild(htiChild))
  530.             ExpandChildren(htiChild);
  531. }
  532. #pragma warn .pia
  533.  
  534. // 
  535. //
  536. //  FUNCTION: ItemHasChild(HTREEITEM)
  537. //
  538. //  PURPOSE: determine if a TreeView item has any children.
  539. //
  540. //  PARAMETERS:
  541. //    hti - handle to a TreeView item.
  542. //
  543. //  RETURN VALUE:
  544. //    TRUE     - The item has children.
  545. //    FALSE    - The item has no children.
  546. //
  547. //  COMMENTS:
  548. //    
  549. //
  550.  
  551. BOOL ItemHasChild(HTREEITEM hti)
  552. {
  553.      _fmemset((LPBYTE)&tvi, 0, sizeof(TV_ITEM));
  554.     tvi.hItem = hti;
  555.     tvi.mask = TVIF_CHILDREN;
  556.     TreeView_GetItem(hwndTreeView, &tvi);
  557.     return (tvi.cChildren) ? TRUE : FALSE;
  558. }
  559.  
  560.